﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Threading;

namespace Logging
{
	public class CLogger
	{
		static public bool ExceptionSaveingEnabled = true;
		static int m_iExceptionCounter = 0;

		static private bool m_bLogEnabled = false;

		static StreamWriter m_oFile;
		static string m_sFilename;
		static public bool AsyncWriting = true;
		static int m_iLogCounter = 0;

		static Mutex m_oFileMutex = new Mutex(false);

		static public void ReportException(Exception e)
		{
			FileStream fs;
			String l_sFilePath = m_iExceptionCounter++.ToString() + " " + DateTime.Now.ToString("ddMMyy_HHmmss.fff") + ".bin";
			
			if (ExceptionSaveingEnabled)
			{

				try
				{
					fs = File.Open(l_sFilePath, FileMode.Create);
					BinaryFormatter b = new BinaryFormatter();
					b.Serialize(fs, e);
					fs.Close();
				}
				catch (Exception l_oException)
				{
				}
			}
		}

		static public void StartLogging(string a_sFilename)
		{
			try
			{
				m_oFile = new StreamWriter(a_sFilename, false, Encoding.ASCII);
				m_oFile.AutoFlush = true;

				m_sFilename = a_sFilename;
				m_bLogEnabled = true;
			}
			catch
			{

			}
		}

		static public void StopLogging()
		{
			m_bLogEnabled = false;
			m_oFile.Close();
		}

		static private void WriteSync(object a_sMessage)
		{
			if (!(m_bLogEnabled))
				return;

			try
			{
				m_oFileMutex.WaitOne();

				m_oFile.WriteLine((string)a_sMessage);
			}
			finally
			{
				m_oFileMutex.ReleaseMutex();
			}
		}

		static private void Write(string a_sMessage)
		{
			if (m_bLogEnabled)
			{
				if (AsyncWriting)
					ThreadPool.QueueUserWorkItem(new WaitCallback(WriteSync), a_sMessage);
				else
					WriteSync(a_sMessage);
			}
		}

		static public void LogMessage(string a_sMessage)
		{
			Write(string.Format("{0},{1}, {2}", DateTime.Now.ToString("dd/MM/yy HH:mm:ss.ffff"), m_iLogCounter++.ToString(), a_sMessage));
		}

		static public void LogFileMessage(string a_sCourse, string a_sFolder, string a_sFile, string a_sMessage)
		{
			LogMessage(string.Format("{0},{1},{2},{3}", a_sCourse ,a_sFolder ,a_sFile ,a_sMessage));
		}

		static public void LogFunctionEntry(params object[] a_aoParams)
		{
			System.Reflection.MethodBase l_oMethod = new System.Diagnostics.StackTrace().GetFrame(1).GetMethod();
			String l_sName = l_oMethod.Name;

			String l_sMessage = "Entered " + l_sName;

			if ((a_aoParams != null) && (a_aoParams.Length > 0))
			{
				l_sMessage += " (";

				foreach (object l_oParam in a_aoParams)
				{
					l_sMessage += " " + l_oParam.ToString();
				}

				l_sMessage += ")";
			}		
			LogMessage(l_sMessage);
		}

		/// <summary>
		/// Add the method name to the log
		/// </summary>
		/// <param name="a_sMessage">A message to be added to the log entry</param>
		/// <param name="a_oParams">Method parameters</param>
		public void LogMethod(string a_sMessage, params string[] a_oParams)
		{
			string l_sMessage = "";
			string l_sMethodName = new System.Diagnostics.StackTrace().GetFrame(1).GetMethod().Name;
			//l_sMessage = methodName + "(";

			l_sMessage = string.Format("{0},{1},", a_sMessage, l_sMethodName);
			for (int i = 0; i < a_oParams.Length; i++)
			{
				if (i != a_oParams.Length - 1)
				{
					l_sMessage += " " + a_oParams[i] + ",";
				}
				else
				{
					l_sMessage += " " + a_oParams[i];
				}
			}
			LogMessage(l_sMessage);// + ");");
		}
	}
}
